<script setup lang="ts">
/**
 * @name StatisticalIndicatorDataEntry
 * @description 统计指标数据录入
 */
import dayjs from 'dayjs'
import type { DatePickerProps } from 'element-plus'
import IndicatorsTable from './components/IndicatorsTable/IndicatorsTable.vue'
import EntryDataTable from './components/EntryDataTable/EntryDataTable.vue'
import YearRangePicker from './components/YearRangePicker/YearRangePicker.vue'
import { useEntryStatisticalndicators } from '@/mixins/StatisticalIndicators/MixinEntryStatisticalIndicators'
import {
  useEntryData,
} from '@/mixins/StatisticalIndicators/MixinEntryData'
import { STORAGE_MODES } from '@/enum/modules/indicator'

import type { Point } from '@/components/ReadonlyPointTree/ReadonlyPointTree'
import type { IndicatorInfo } from '@/types'
import { indicatorSubmitApi } from '@/api'

type PickerType = DatePickerProps['type']

const {
  loading: indicatorsLoading,
  lists: indicators,
  queryEntryIndicatorsByPointId,
} = useEntryStatisticalndicators()
const [selectedIndicator, setSelectedIndicator]
  = useState<IndicatorInfo | null>(null)
const [timeTypeList, setTimeTypeList] = useState<number[]>(
  [],
)

const [time, setTime] = useState('')
const [timeType, setTimeType] = useState(0)
const allTimeTypeList = [
  { label: '小时', value: STORAGE_MODES.HOUR },
  { label: '日', value: STORAGE_MODES.DAY },
  { label: '月', value: STORAGE_MODES.MONTH },
  { label: '年', value: STORAGE_MODES.YEAR },
]
const timeTypeOptions = computed(() => {
  const o = allTimeTypeList.filter(item =>
    timeTypeList.value.includes(
      item.value as unknown as number,
    ),
  )
  return o
})

const pickerType = computed<PickerType>(() => {
  const type = unref(timeType)
  switch (type as unknown as STORAGE_MODES) {
    case STORAGE_MODES.DAY:
      return 'month'
    case STORAGE_MODES.MONTH:
    case STORAGE_MODES.YEAR:
      return 'year'
    default:
      return 'date'
  }
})
const pickerFormatter = computed(() => {
  const type = unref(timeType)
  switch (type as unknown as STORAGE_MODES) {
    case STORAGE_MODES.DAY:
      return 'YYYY-MM'
    case STORAGE_MODES.MONTH:
    case STORAGE_MODES.YEAR:
      return 'YYYY'
    default:
      return 'YYYY-MM-DD'
  }
})

const {
  loading: dataLoading,
  lists: data,
  setLists: setData,
  getEntryDataByIndicatorId,
  saving,
  saveOrUpdateEntryData,
} = useEntryData()

function disabledDate(date: Date) {
  return date.getTime() > Date.now() - 24 * 60 * 60 * 1000
}

function getResetTimeOfTimeType(val: STORAGE_MODES) {
  switch (val) {
    case STORAGE_MODES.DAY:
      return dayjs().format('YYYY-MM')
    case STORAGE_MODES.MONTH:
      return dayjs().format('YYYY')
    case STORAGE_MODES.YEAR:
      // 默认为最近6年
      return [
        dayjs().subtract(5, 'year').format('YYYY'),
        dayjs().format('YYYY'),
      ].join('_')
    default:
      return dayjs().format('YYYY-MM-DD')
  }
}

async function handlePointSelected(o: Point) {
  if (o.id) {
    queryEntryIndicatorsByPointId(o.id)
  }
}
async function handleIndicatorSelected(o: IndicatorInfo) {
  if (o.id === unref(selectedIndicator)?.id)
    return
  setSelectedIndicator(o)
  await getTimeTypeList()
  // 指标没有数据存储的情况（一般不会有，但数据问题可能出现）

  const head = timeTypeList.value[0]
  if (!head) {
    setData([])
    return
  }

  // 如果 head 与 timeType 相同，则主动更新数据
  if (head === unref(timeType)) {
    getEntryData()
    return
  }

  // 通过 time change 触发 watch 更新数据
  setTimeType(head)
}

watch(
  () => unref(timeType),
  async (o: number) => {
    const resetedTime = getResetTimeOfTimeType(
      o as unknown as STORAGE_MODES,
    )
    /**
     * 防止 timeType change 后 time 没有变化（如：
     * 15分钟与小时 timeType 不同，resetTimeOnTypeChange 会被触发，
     * 但是 time 没有变化）
     */
    if (unref(time) === resetedTime) {
      setTime('')
      // 等待 time 的 watch 的回调执行完毕，再执行 setTime
      await nextTick()
    }
    setTime(resetedTime)
  },
)

watch(
  () => unref(time),
  () => {
    const tt = unref(timeType)
    const t = unref(time)
    // 以逗号开头或结尾的 time 字符串都是不正确的格式
    if (/^,|,$/.test(t)) {
      ElMessage.warning('时间格式错误')
      return
    }
    if (tt && t) {
      console.log('trigger: ', {
        indicatorId: unref(selectedIndicator)?.id,
        timeType: tt,
        time: t,
      })
      getEntryData()
    }
  },
)

function getEntryData() {
  const indicatorId = unref(selectedIndicator)?.id
  if (indicatorId) {
    let t = ''
    switch (unref(timeType) as unknown as STORAGE_MODES) {
      case STORAGE_MODES.YEAR:
        t = '1y'
        break
      case STORAGE_MODES.MONTH:
        t = '1M'
        break
      case STORAGE_MODES.DAY:
        t = '1d'
        break
      case STORAGE_MODES.HOUR:
        t = '1H'
        break
    }
    getEntryDataByIndicatorId({
      indicatorId,
      timeType: t,
      time: unref(time),
    })
  }
}

async function handleClickSave() {
  console.log(1)
  const indicatorId = unref(selectedIndicator)?.id
  if (indicatorId) {
    let t = ''
    switch (unref(timeType) as unknown as STORAGE_MODES) {
      case STORAGE_MODES.YEAR:
        t = '1y'
        break
      case STORAGE_MODES.MONTH:
        t = '1M'
        break
      case STORAGE_MODES.DAY:
        t = '1d'
        break
      case STORAGE_MODES.HOUR:
        t = '1H'
        break
    }
    saveOrUpdateEntryData({
      indicatorId,
      time: unref(time),
      timeType: t,
      dataList: unref(data),
      indicatorNumber: unref(selectedIndicator)!
        .indicatorNumber,
    })
  }
}
async function getTimeTypeList() {
  const { data: res }
    = await indicatorSubmitApi.listTimeType(
      selectedIndicator.value?.id!,
    )
  const timeObj: Record<string, number> = {
    '1H': STORAGE_MODES.HOUR as unknown as number,
    '1d': STORAGE_MODES.DAY as unknown as number,
    '1M': STORAGE_MODES.MONTH as unknown as number,
    '1y': STORAGE_MODES.YEAR as unknown as number,
  }
  setTimeTypeList(res.map((item: string) => timeObj[item]))
}
</script>

<template>
  <div class="padding-sm roll flex container">
    <div class="points-container">
      <div class="container-head">
        <h3>用能单元</h3>
      </div>
      <div class="roll container-body">
        <ReadonlyPointTree
          fire
          :show-title="false"
          @click-node="handlePointSelected"
        />
      </div>
    </div>
    <div class="margin-left-sm indicators-container">
      <div class="container-head">
        <h3>统计指标</h3>
      </div>
      <div class="container-body alpha-block overflow-auto p-[10px]">
        <IndicatorsTable
          :loading="indicatorsLoading"
          :data="indicators"
          @indicator-selected="handleIndicatorSelected"
        />
      </div>
    </div>
    <div class="margin-left-sm data-container">
      <div class="container-head">
        <h3>数据录入</h3>
      </div>
      <div class="container-body flex-direction alpha-block flex overflow-auto p-[10px]">
        <template v-if="selectedIndicator">
          <div
            class="width-fill align-center description box-border flex border rounded-sm"
          >
            <span class="description-label flex-shrink-0">
              指标名称
            </span>
            <div
              class="flex-fillRemaining description-value"
            >
              {{ selectedIndicator.indicatorName }}
            </div>
          </div>
          <div
            class="width-fill align-center description box-border flex border rounded-sm"
          >
            <span class="description-label flex-shrink-0">
              指标编码
            </span>
            <div
              class="flex-fillRemaining description-value"
            >
              {{ selectedIndicator.indicatorNumber }}
            </div>
          </div>
          <div class="clearfix">
            <div
              class="margin-top-sm align-center data-filter flex flex-wrap"
            >
              <span
                class="flex-shrink-0 text-right"
                style="
                  width: 80px;
                  font-size: var(--el-font-size-base);
                "
              >
                时间类型：
              </span>
              <ElSelect
                v-model="timeType"
                placeholder="请选择"
                class="free type-select"
              >
                <ElOption
                  label="请选择"
                  :value="0"
                  disabled
                />
                <ElOption
                  v-for="item in timeTypeOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </ElSelect>
            </div>
            <div
              class="margin-top-sm align-center data-filter flex flex-wrap"
            >
              <span
                class="flex-shrink-0 text-right"
                style="
                  width: 80px;
                  font-size: var(--el-font-size-base);
                "
              >
                时间：
              </span>
              <YearRangePicker
                v-if="timeType === STORAGE_MODES.YEAR as unknown as number"
                v-model="time"
              />
              <ElDatePicker
                v-else
                v-model="time"
                class="time-picker free"
                :type="pickerType"
                :format="pickerFormatter"
                :value-format="pickerFormatter"
                :clearable="false"
              />
            </div>
            <div class="margin-top-sm data-filter">
              <ElButton
                class="margin-left-auto"
                type="primary"
                :loading="saving"
                @click="handleClickSave"
              >
                保存
              </ElButton>
            </div>
          </div>
          <EntryDataTable
            v-model="data"
            :loading="dataLoading"
            :unit="selectedIndicator?.unit"
            class="margin-top-sm"
          />
        </template>
        <div v-else class="container-empty">
          <TableEmpty
            :image-size="120"
            text="选中统计指标查看数据录入"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.roll {
  @include roll();
}
.points-container,
.indicators-container,
.data-container {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.points-container {
  --container-left-width: 100%;
}
.points-container {
  flex: 1;
  min-width: 200px;
  max-width: 340px;
}
.indicators-container {
  flex: 1;
  min-width: 260px;
  max-width: 460px;
}
.data-container {
  flex: 1;
  min-width: 400px;
}
.container-head {
  flex-shrink: 0;
  > h3 {
    margin: 0;
  }
}
.container-body {
  margin-top: 20px;
  flex: 1;
}
.container-empty {
  height: 100%;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.description {
  font-size: var(--el-font-size-base);
  & + .description {
    margin-top: -1px;
  }
}
.description-label,
.description-value {
  padding: 12px 20px;
}
.description-label {
  background: var(--el-bg-color-page);
}
.data-filter {
  float: left;
  margin-right: 15px;
}
.type-select {
  width: 120px;
}
.type-select :deep(.el-input) {
  min-width: auto !important;
}
.type-select :deep(.el-input__wrapper) {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
:deep(.time-picker) {
  margin-left: -1px;
}
:deep(.time-picker .el-input__wrapper) {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
</style>
